package com.zm.demo.core.leetcode;

import java.util.HashMap;
import java.util.Map;

/**
 * 给出一个二维数组 A，每个单元格为 0（代表海）或 1（代表陆地）。

 移动是指在陆地上从一个地方走到另一个地方（朝四个方向之一）或离开网格的边界。

 返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。

 来源：力扣（LeetCode）
 链接：https://leetcode-cn.com/problems/number-of-enclaves
 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
class NumEnclaves {
    public int numEnclaves(int[][] A) {
        if(A.length <= 2){
            return 0;
        }

        if (A[1].length <=2){
            return 0;
        }

        int count=0;
        for(int i = 1 ; i < A.length-1; i++){
            for (int j = 1; j<A[i].length-1; j++){
                Map<String, Boolean> calced =new HashMap();
                if(A[i][j] == 1 &&
                 calcRoeDecre(A, i-1, j, calced) && calcRowIncre(A, i+1, j, calced)
                    && calcColDecre(A, i, j-1, calced) && calcColIncre(A, i, j+1, calced)){
                        count++;
                    }

            }
        }
        return count;

    }

       //某方向不能出去返回true
    public boolean calcRoeDecre(int[][] A, int row,int col,Map<String, Boolean>calced){
        
            if(row < A.length && col<A[1].length && row >=0 && col >= 0){
                if(A[row][col] == 1){
                    String s1 = col + "" +  (row -1) + "" + (row);
                    String s2 = row + "" + (col-1 ) + "" + (col); 
                    String s3 = row + "" + (col ) + "" + (col+1); 
                    
                    boolean result = true;
                    if (calced.get(s1)==null || !calced.get(s1)){
                        calced.put(s1,true);
                        result = result && calcRowIncre(A, row - 1, col, calced);
                        
                    }
                    if(calced.get(s2)==null || !calced.get(s2)){
                        calced.put(s2,true);
                        result = result && calcColDecre(A, row, col-1,  calced);
                    }

                    if(calced.get(s3)==null || !calced.get(s3)){
                        calced.put(s3,true);
                        result = result && calcColIncre(A, row, col+1, calced);
                    }

                    return result;
                }else{
                    return true;
                }
            }else{
                return false;
            }
        }
    //某方向不能出去返回true
    public boolean calcRowIncre(int[][] A, int row,int col, Map<String, Boolean>calced){
        
            if(row < A.length && col<A[1].length && row >=0 && col >= 0){
                if(A[row][col] == 1){
                    String s1 = col + "" +  (row ) + "" + (row+1);
                    String s2 = row + "" + (col-1 ) + "" + (col); 
                    String s3 = row + "" + (col ) + "" + (col+1); 
                    
                    boolean result = true;
                    if (calced.get(s1)==null || !calced.get(s1)){
                        calced.put(s1,true);
                        result = result && calcRowIncre(A, row + 1, col, calced);
                        
                    }
                    if(calced.get(s2)==null || !calced.get(s2)){
                        calced.put(s2,true);
                        result = result && calcColDecre(A, row, col-1,  calced);
                    }

                    if(calced.get(s3)==null || !calced.get(s3)){
                        calced.put(s3,true);
                        result = result && calcColIncre(A, row, col+1, calced);
                    }

                    return result;
                }else{
                    return true;
                }
            }else{
                return false;
            }
        }

    //某方向不能出去返回true
    public boolean calcColDecre(int[][] A, int row,int col, Map<String, Boolean>calced){
        
            if(row < A.length && col<A[1].length && row >=0 && col >= 0){
                if(A[row][col] == 1){
                    String s1 = col + "" + (row -1) + "" + row; 
                    String s2 = col + "" + (row ) + "" + (row+1); 
                    String s3 = row + "" + (col-1 ) + "" + (col); 
                    
                    boolean result = true;
                    if (calced.get(s1)==null || !calced.get(s1)){
                        calced.put(s1,true);
                        result = result && calcRoeDecre(A, row -1, col, calced);
                    }
                    if(calced.get(s2)==null || !calced.get(s2)){
                        calced.put(s2,true);
                        result = result && calcRowIncre(A, row + 1, col, calced);
                    }

                    if(calced.get(s3)==null || !calced.get(s3)){
                        calced.put(s3,true);
                        result = result && calcColDecre(A, row, col-1, calced);
                    }

                    return result;
                }else{
                    return true;
                }
            }else{
                return false;
            }
        }

     public boolean calcColIncre(int[][] A, int row,int col, Map<String, Boolean>calced){   

            if(row < A.length && col<A[1].length && row >=0 && col >= 0){
                if(A[row][col] == 1){
                    String s1 = col + "" + (row -1) + "" + row; 
                    String s2 = col + "" + (row ) + "" + (row+1); 
                    String s3 = row + "" + (col ) + "" + (col+1); 
                    
                    boolean result = true;
                    if (calced.get(s1)==null || !calced.get(s1)){
                        calced.put(s1,true);
                        result = result && calcRoeDecre(A, row -1, col, calced);
                    }
                    if(calced.get(s2)==null || !calced.get(s2)){
                        calced.put(s2,true);
                        result = result && calcRowIncre(A, row + 1, col, calced);
                    }

                    if(calced.get(s3)==null || !calced.get(s3)){
                        calced.put(s3,true);
                        result = result && calcColIncre(A, row, col+1, calced);
                    }

                    return result;
                }else{
                    return true;
                }
            }else{
                return false;
            }
        }
}